/*
 * CSV.cpp
 *
 *  Created on: Jan 15, 2011
 *      Author: LyonsDesktop
 */

#include "CSV.h"
#include "string.h"
#include <set>
#include <stdlib.h>
#include <unordered_map>

using namespace CLEVER::Datasets::Formats;
using namespace std;

std::vector<std::string> Tokenize(const std::string& str, const std::string& delim)
{


    std::vector<std::string> tokens;
    char* c_str=(char*)str.c_str();
    char * pch;
    pch = strtok (c_str,delim.c_str());
    tokens.push_back(string(pch));
    while(pch!=NULL)
    {
    	pch = strtok (NULL,delim.c_str());
    	if(pch != NULL)
    		tokens.push_back(string(pch));
    }

//    size_t p0 = 0, p1 = std::string::npos;
//
//    while(p0 != std::string::npos)
//    {
//        p1 = str.find_first_of(delim, p0);
//        if (p1 != p0)
//        {
//            std::string token = str.substr(p0, p1 - p0);
//			if (token != "") { tokens.push_back(token); }
//        }
//        p0 = str.find_first_not_of(delim, p1);
//    }

    return tokens;
}

double* Tokenize(const std::string& str, const std::string& delim, int rNumAtt)
{

//	std::cout<<"Tokenize string: "<<str<<std::endl;
    double* tokens=new double[rNumAtt];
    char* c_str=(char*)str.c_str();
    char * pch;
    int iAtt=0;
    pch = strtok (c_str,delim.c_str());
    tokens[iAtt]=atof(pch);
    while(pch!=NULL)
    {
    	pch = strtok (NULL,delim.c_str());
    	if(pch != NULL)
    		tokens[++iAtt]=atof(pch);
    }

//    size_t p0 = 0, p1 = std::string::npos;
//
//    while(p0 != std::string::npos)
//    {
//        p1 = str.find_first_of(delim, p0);
//        if (p1 != p0)
//        {
//            std::string token = str.substr(p0, p1 - p0);
//			if (token != "") { tokens.push_back(token); }
//        }
//        p0 = str.find_first_not_of(delim, p1);
//    }

    return tokens;
}

CSVReader::CSVReader(const char* filename)
{

	std::ifstream* infile = new ifstream(filename);
	if (!infile->is_open()) { return; }

	std::string str = "";
	while (!infile->eof())
	{

		 char c = infile->get();
		 if (c == '\r' || c == '\n')
		 {
			 if (str != "") { lines.push_back(str); }
			 str = "";
		 }
		 else { str += c; }
	}
}
CSVReader::CSVReader(const char* filename, double* realData, double* metaData, unsigned int rExamples
		, int rNumRealAtt, int rNumMetaAtt, set<double>& wclusterIDKeys)
{
	std::ifstream* infile = new ifstream(filename);
	if (!infile->is_open()) { return; }

	std::cout<<"File is opened"<<std::endl;

	std::string str = "";
	unsigned iline=0;
	int rNumAtt=rNumMetaAtt+rNumRealAtt;

//	set<double> metaKeys;//only used for Yahoo's benchmark


	while (!infile->eof())
	{
		 char c = infile->get();
		 if (c == '\r' || c == '\n')
		 {
			 if (str != "")
			 {
				 double* tokens=Tokenize(str,",",rNumAtt);
				 int lptr=0;
				 for(int iReal=0;iReal<rNumRealAtt;iReal++)
				 {
				 	double v = tokens[lptr++];
//					 std::cout<<tokens[iReal]<<":"<<v<<" ";
				 	//std::stringstream ss(tokens[lptr++]);
//
				 	realData[iline*rNumRealAtt + iReal]=v;
				 }
//
				 for(int iMeta=0;iMeta<rNumMetaAtt;iMeta++)
				 {
				 	double v = tokens[lptr++];
				 	metaData[iline*rNumMetaAtt + iMeta]=v;
//				 	if(iMeta==1)//only take care the meta keys for cluster id
//				 	{
//				 		wclusterIDKeys.insert(v);
//				 	}
				 }

			 }
			 if(iline%1000000==0 && iline>1)
				 std::cout<<iline<<" lines loaded "<<std::endl;
			 iline++;
			 str = "";
		 }
		 else {
			 str+=c;
		 }
	}


//	while (!infile->eof())
//	{
//		 char c = infile->get();
//		 if (c == '\r' || c == '\n')
//		 {
//			 if (str != "") { lines.push_back(str); }
//			 str = "";
//		 }
//		 else { str += c; }
//	}
}

int CSVReader::NumLines()
{
	return lines.size();
}

std::vector<std::string> CSVReader::GetLine(int line_index)
{
	return Tokenize(lines[line_index], ",");
}

CSVWriter::CSVWriter(const char* filename)
{
	outfile = new ofstream(filename);
	hasline = false;
}

void CSVWriter::WriteValue(double v)
{
	if (hasline) { *outfile << ',';}
	hasline = true;
	*outfile << v;
}

void CSVWriter::Newline()
{
	*outfile << endl;
	hasline = false;
}

void CSVWriter::Close()
{
	if (outfile->is_open())
	{
		outfile->flush();
		outfile->close();
	}
}

CSVWriter::~CSVWriter()
{
	Close();
}
